/*
 * Class: PlaylistGenerator
 * 
 * Created on Sep 27, 2013
 * 
 * (c) Copyright by Minh Tran
 * Global Cybersoft VN.
 * Floor 3-4-5, Helios Building, Quang Trung Software City
 */
package com.minh.tran.sg;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.minh.tran.sg.model.Song;

/**
 * The Class PlaylistGenerator.
 */
public class PlaylistGenerator
{

    /** The Constant LOG. */
    private static final Log LOG = LogFactory.getLog(PlaylistGenerator.class);

    public static void main(String[] args)
    {
        List<Song> lst = new ArrayList<Song>();

        Song song1 = new Song("http://www.nhaccuatui.com/bai-hat/trang-vo-dan-truong.djoZODkM7ROU.html");
        song1
            .setLocation("http://s91.stream.nixcdn.com/622f8bd0e7fa988b1fafc150c42b8dde/5245ace4/NCTOfficial2/TrangVo-DanTruong_bby.mp3");
        lst.add(song1);

        Song song = new Song("http://www.nhaccuatui.com/bai-hat/tieng-ru-ngay-xua-dan-truong.Jw5tds8gjc.html");
        song.setLocation("http://s91.stream.nixcdn.com/ebefcf4c606b4434f04226363b788d9a/5245ace4/NhacCuaTui103/TiengRuNgayXua-DanTruong_pg8h.mp3");
        lst.add(song);
        PlaylistGenerator play = new PlaylistGenerator("Hello", lst);
        play.generate("D:\\test.wpl");
    }

    /** The number of songs. */
    private int numberOfSongs = 0;

    /** The title. */
    private String title = "";

    /** The list songs. */
    private final List<Song> lstSongs;

    /**
     * Instantiates a new playlist generator.
     *
     * @param title the title
     * @param lstSongs the list songs
     */
    public PlaylistGenerator(final String title, final List<Song> lstSongs)
    {
        this.numberOfSongs = lstSongs.size();
        this.title = title;
        this.lstSongs = lstSongs;
    }

    /**
     * Generate.
     */
    public boolean generate(String fileLocation)
    {
        try
        {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            this.appendSmilElement(doc);
            return this.writeANewXMLFile(doc, fileLocation);
        }
        catch (ParserConfigurationException e)
        {
            LOG.error("Exception: ParserConfigurationException");
            return false;
        }
        catch (TransformerException e)
        {
            LOG.error("Exception: TransformerException");
            return false;
        }
    }

    private boolean writeANewXMLFile(Document doc, String fileLocation) throws TransformerException
    {
        try
        {
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            File file = new File(fileLocation);
            if (!file.exists())
            {
                file.createNewFile();
            }
            StreamResult result = new StreamResult(file);
            transformer.transform(source, result);
            System.out.println("File saved!");
            return true;
        }
        catch (IOException e)
        {
            LOG.error("Exception: IOException");
            return false;
        }
    }

    /**
     * Append smil element.
     *
     * @param doc the doc
     */
    private void appendSmilElement(Document doc)
    {
        Element eleSmil = doc.createElement("smil");
        doc.appendChild(eleSmil);
        this.appendHeadElement(doc, eleSmil);
        this.appendBodyElement(doc, eleSmil);
    }

    /**
     * Append body element.
     *
     * @param doc the doc
     * @param eleSmil the ele smil
     */
    private void appendBodyElement(Document doc, Element eleSmil)
    {
        Element eleBody = doc.createElement("body");
        eleSmil.appendChild(eleBody);

        Element eleSeq = doc.createElement("seq");
        eleBody.appendChild(eleSeq);

        for (Song song : this.lstSongs)
        {
            this.appendMediaElement(doc, eleSeq, song);
        }
    }

    /**
     * Append seq element.
     *
     * @param doc the doc
     * @param eleBody the ele body
     * @param song the song
     */
    private void appendMediaElement(Document doc, Element eleSeq, Song song)
    {
        Element eleMedia = doc.createElement("media");
        eleSeq.appendChild(eleMedia);

        Attr atrSrc = doc.createAttribute("src");
        atrSrc.appendChild(doc.createTextNode(song.getLocation()));
        eleMedia.setAttributeNode(atrSrc);
    }

    /**
     * Append head element.
     *
     * @param doc the doc
     * @param eleSmil the ele smil
     */
    private void appendHeadElement(Document doc, Element eleSmil)
    {
        Element eleHead = doc.createElement("head");
        eleSmil.appendChild(eleHead);

        this.appendMetaElement(doc, eleHead, "Generator", "Microsoft Windows Media Player -- 12.0.7601.17514");
        this.appendMetaElement(doc, eleHead, "ItemCount", String.valueOf(this.numberOfSongs));

        Element eleTitle = doc.createElement("title");
        eleTitle.appendChild(doc.createTextNode(this.title));
        eleHead.appendChild(eleTitle);
    }

    /**
     * Append meta element.
     *
     * @param doc the doc
     * @param eleHead the ele head
     * @param string the string
     * @param string2 the string2
     */
    private void appendMetaElement(Document doc, Element eleHead, String string, String string2)
    {
        Element meta = doc.createElement("meta");
        eleHead.appendChild(meta);

        Attr content = doc.createAttribute("content");
        content.setValue(string2);
        meta.setAttributeNode(content);

        Attr name = doc.createAttribute("name");
        name.setValue(string);
        meta.setAttributeNode(name);
    }

}
